import { MigrationInterface, QueryRunner } from 'typeorm';

export class TypeORMInitialSchema1744911876759 implements MigrationInterface {
  name = 'TypeORMInitialSchema1744911876759';

  public async up(queryRunner: QueryRunner): Promise<void> {
    // Check if enum type exists before creating it
    const enumExists = await queryRunner.query(
      `SELECT 1 FROM pg_type JOIN pg_catalog.pg_namespace ON pg_namespace.oid = pg_type.typnamespace WHERE typname = 'devices_status_enum' AND nspname = 'public'`,
    );

    if (!enumExists || enumExists.length === 0) {
      await queryRunner.query(
        `CREATE TYPE "public"."devices_status_enum" AS ENUM('inactive', 'active', 'lost', 'retired', 'disabled')`,
      );
    }

    // Create devices table if not exists
    await queryRunner.query(
      `CREATE TABLE IF NOT EXISTS "devices" ("id" uuid NOT NULL DEFAULT uuid_generate_v4(), "serial_number" character varying(64) NOT NULL, "status" "public"."devices_status_enum" NOT NULL DEFAULT 'active', "registered_by" uuid, "registered_at" TIMESTAMP NOT NULL DEFAULT now(), "last_used_at" TIMESTAMP, "user_id" uuid, "metadata" json, CONSTRAINT "UQ_cc9e89897e336172fd06367735d" UNIQUE ("serial_number"), CONSTRAINT "PK_b1514758245c12daf43486dd1f0" PRIMARY KEY ("id"))`,
    );

    // Check if users_role_enum exists
    const usersRoleEnumExists = await queryRunner.query(
      `SELECT 1 FROM pg_type JOIN pg_catalog.pg_namespace ON pg_namespace.oid = pg_type.typnamespace WHERE typname = 'users_role_enum' AND nspname = 'public'`,
    );

    if (!usersRoleEnumExists || usersRoleEnumExists.length === 0) {
      await queryRunner.query(`CREATE TYPE "public"."users_role_enum" AS ENUM('user', 'admin')`);
    }

    // Continue with remaining table creation using IF NOT EXISTS
    await queryRunner.query(
      `CREATE TABLE IF NOT EXISTS "users" ("id" uuid NOT NULL DEFAULT uuid_generate_v4(), "username" character varying(64) NOT NULL, "password_hash" character varying(128) NOT NULL, "role" "public"."users_role_enum" NOT NULL DEFAULT 'user', "display_name" character varying(64), "phone" character varying(32), "created_at" TIMESTAMP NOT NULL DEFAULT now(), "last_login_at" TIMESTAMP, "is_active" boolean NOT NULL DEFAULT true, "deactivation_reason" character varying(255), CONSTRAINT "UQ_fe0bb3f6520ee0469504521e710" UNIQUE ("username"), CONSTRAINT "UQ_a000cca60bcf04454e727699490" UNIQUE ("phone"), CONSTRAINT "PK_a3ffb1c0c8416b9fc6f907b7433" PRIMARY KEY ("id"))`,
    );
    await queryRunner.query(
      `CREATE TABLE IF NOT EXISTS "device_audit_codes" ("auditNumber" character varying(64) NOT NULL, "verifyCode" character varying(64) NOT NULL, "createdAt" TIMESTAMP NOT NULL DEFAULT now(), "usedAt" TIMESTAMP, "deviceSerialNumber" character varying(64), "createdBy" character varying NOT NULL, "isDeleted" boolean NOT NULL DEFAULT false, "created_by" uuid, "device_serial_number" character varying(64), CONSTRAINT "PK_faeaccd969a76fff586c5d508f2" PRIMARY KEY ("auditNumber"))`,
    );
    await queryRunner.query(
      `CREATE TABLE IF NOT EXISTS "task_categories" ("id" uuid NOT NULL DEFAULT uuid_generate_v4(), "name" character varying(64) NOT NULL, "description" text, "is_deleted" boolean NOT NULL DEFAULT false, CONSTRAINT "PK_40776b70c03a33e93c8c0165f87" PRIMARY KEY ("id"))`,
    );
    await queryRunner.query(
      `CREATE TABLE IF NOT EXISTS "task_templates" ("id" uuid NOT NULL DEFAULT uuid_generate_v4(), "title" character varying(128) NOT NULL, "description" text, "task_category_id" uuid NOT NULL, "version" integer NOT NULL DEFAULT '1', "created_by" uuid NOT NULL, "created_at" TIMESTAMP NOT NULL DEFAULT now(), "updated_at" TIMESTAMP NOT NULL DEFAULT now(), "is_deleted" boolean NOT NULL DEFAULT false, CONSTRAINT "PK_a1347b5446b9e3158e2b72f58b2" PRIMARY KEY ("id"))`,
    );

    // Check for tasks_type_enum and tasks_status_enum
    const tasksTypeEnumExists = await queryRunner.query(
      `SELECT 1 FROM pg_type JOIN pg_catalog.pg_namespace ON pg_namespace.oid = pg_type.typnamespace WHERE typname = 'tasks_type_enum' AND nspname = 'public'`,
    );

    if (!tasksTypeEnumExists || tasksTypeEnumExists.length === 0) {
      await queryRunner.query(`CREATE TYPE "public"."tasks_type_enum" AS ENUM('single', 'global')`);
    }

    const tasksStatusEnumExists = await queryRunner.query(
      `SELECT 1 FROM pg_type JOIN pg_catalog.pg_namespace ON pg_namespace.oid = pg_type.typnamespace WHERE typname = 'tasks_status_enum' AND nspname = 'public'`,
    );

    if (!tasksStatusEnumExists || tasksStatusEnumExists.length === 0) {
      await queryRunner.query(
        `CREATE TYPE "public"."tasks_status_enum" AS ENUM('not_start', 'completed', 'removed')`,
      );
    }

    await queryRunner.query(
      `CREATE TABLE IF NOT EXISTS "tasks" ("id" uuid NOT NULL DEFAULT uuid_generate_v4(), "title" character varying(128) NOT NULL, "description" text, "type" "public"."tasks_type_enum" NOT NULL DEFAULT 'single', "task_category_id" uuid NOT NULL, "parent_task_id" uuid, "assigned_user_id" uuid, "start_time" TIMESTAMP, "status" "public"."tasks_status_enum" NOT NULL DEFAULT 'not_start', "due_time" TIMESTAMP, "completed_at" TIMESTAMP, "cron_expression" character varying(32), "created_at" TIMESTAMP NOT NULL DEFAULT now(), "updated_at" TIMESTAMP NOT NULL DEFAULT now(), "is_deleted" boolean NOT NULL DEFAULT false, "task_template_id" uuid, CONSTRAINT "PK_8d12ff38fcc62aaba2cab748772" PRIMARY KEY ("id"))`,
    );
    await queryRunner.query(
      `CREATE TABLE IF NOT EXISTS "attachments" ("id" uuid NOT NULL DEFAULT uuid_generate_v4(), "file_url" character varying(1024) NOT NULL, "file_name" character varying(255) NOT NULL, "attachment_type" character varying(100), "created_by" character varying NOT NULL, "content_id" uuid, "created_at" TIMESTAMP NOT NULL DEFAULT now(), CONSTRAINT "PK_5e1f050bcff31e3084a1d662412" PRIMARY KEY ("id"))`,
    );

    // Check for contents_content_type_enum
    const contentsContentTypeEnumExists = await queryRunner.query(
      `SELECT 1 FROM pg_type JOIN pg_catalog.pg_namespace ON pg_namespace.oid = pg_type.typnamespace WHERE typname = 'contents_content_type_enum' AND nspname = 'public'`,
    );

    if (!contentsContentTypeEnumExists || contentsContentTypeEnumExists.length === 0) {
      await queryRunner.query(
        `CREATE TYPE "public"."contents_content_type_enum" AS ENUM('text', 'markdown')`,
      );
    }

    await queryRunner.query(
      `CREATE TABLE IF NOT EXISTS "contents" ("id" uuid NOT NULL DEFAULT uuid_generate_v4(), "title" character varying(128) NOT NULL, "content_type" "public"."contents_content_type_enum" NOT NULL DEFAULT 'text', "body" text NOT NULL, "recommend_reason" text, "template_id" uuid, "created_by" uuid NOT NULL, "created_at" TIMESTAMP NOT NULL DEFAULT now(), "updated_at" TIMESTAMP NOT NULL DEFAULT now(), "is_approved" boolean NOT NULL DEFAULT false, "is_deleted" boolean NOT NULL DEFAULT false, CONSTRAINT "PK_b7c504072e537532d7080c54fac" PRIMARY KEY ("id"))`,
    );
    await queryRunner.query(
      `CREATE TABLE IF NOT EXISTS "content_tag_mapping" ("content_id" uuid NOT NULL, "tag_id" uuid NOT NULL, "created_at" TIMESTAMP NOT NULL DEFAULT now(), CONSTRAINT "PK_d10568e242951531b555817f355" PRIMARY KEY ("content_id", "tag_id"))`,
    );
    await queryRunner.query(
      `CREATE TABLE IF NOT EXISTS "tags" ("id" uuid NOT NULL DEFAULT uuid_generate_v4(), "name" character varying(64) NOT NULL, CONSTRAINT "UQ_d90243459a697eadb8ad56e9092" UNIQUE ("name"), CONSTRAINT "PK_e7dc17249a1148a1970748eda99" PRIMARY KEY ("id"))`,
    );
  }

  public async down(queryRunner: QueryRunner): Promise<void> {
    // In production, we should never drop tables as it would delete all data
    // Instead, we log a warning and throw an error to prevent accidental execution

    console.warn('⚠️ WARNING: Attempting to revert the initial schema migration.');
    console.warn('⚠️ This would DROP ALL TABLES and DELETE ALL DATA.');
    console.warn('⚠️ This operation has been disabled for safety.');

    // If you absolutely need to drop all tables, you can uncomment the code below
    // and run the migration revert manually with full awareness of the consequences.

    /*
        await queryRunner.query(`DROP TABLE "tags"`);
        await queryRunner.query(`DROP TABLE "content_tag_mapping"`);
        await queryRunner.query(`DROP TABLE "contents"`);
        await queryRunner.query(`DROP TYPE "public"."contents_content_type_enum"`);
        await queryRunner.query(`DROP TABLE "attachments"`);
        await queryRunner.query(`DROP TABLE "tasks"`);
        await queryRunner.query(`DROP TYPE "public"."tasks_status_enum"`);
        await queryRunner.query(`DROP TYPE "public"."tasks_type_enum"`);
        await queryRunner.query(`DROP TABLE "task_templates"`);
        await queryRunner.query(`DROP TABLE "task_categories"`);
        await queryRunner.query(`DROP TABLE "device_audit_codes"`);
        await queryRunner.query(`DROP TABLE "users"`);
        await queryRunner.query(`DROP TYPE "public"."users_role_enum"`);
        await queryRunner.query(`DROP TABLE "devices"`);
        await queryRunner.query(`DROP TYPE "public"."devices_status_enum"`);
        */
  }
}
